﻿Namespace Tools
    Public Class TextParser

        Private _text As String
        ''' <summary>
        ''' Il testo che viene parserizzato.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Text() As String
            Get
                Return _text
            End Get
        End Property

        ''' <summary>
        ''' True se l'ultima operazione MoveNext ha spostato il puntatore.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property HasMoved() As Boolean
            Get
                Return _hasMoved
            End Get
        End Property
        Private _hasMoved As Boolean

        ''' <summary>
        ''' Returns the Text from the current position.
        ''' </summary>
        ''' <value></value>
        ''' <returns>See summary.</returns>
        ''' <remarks></remarks>
        Public ReadOnly Property SubText() As String
            Get
                Try
                    Return Mid(Text, Position)
                Catch ex As Exception
                    Return String.Empty
                End Try
            End Get
        End Property

        Private _position As Integer = 1
        ''' <summary>
        ''' Indica la posizione (o puntatore) all'interno del testo
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Position() As Integer
            Get
                Return _position
            End Get
            Set(ByVal value As Integer)
                _position = value
            End Set
        End Property

        ''' <summary>
        ''' Crea una nuova istanza di TextParser
        ''' </summary>
        ''' <param name="Text">Il testo da parserizzare</param>
        ''' <remarks></remarks>
        Public Sub New(ByVal Text As String)
            _text = Text
        End Sub

        ''' <summary>
        ''' Sposta il puntatore nel file (Position) al carattere successivo alla prima occorrenza della stringa cercata. Restituisce la nuova posizione. Se la stringa non viene trovata restituisce -1.
        ''' </summary>
        ''' <param name="SearchText">La stringa da cercare</param>
        ''' <returns></returns>
        ''' <remarks>La ricerca verrà effettuata a partire dalla posizione corrente. Usare il metodo Reset per effettuare la ricerca dall'inizio del testo. Nel caso in cui la stringa non venga trovata, il puntatore non verrà spostato.</remarks>
        Public Function MoveNext(ByVal SearchText As String) As Integer

            Dim searchPos As Integer = InStr(Position, Text, SearchText)

            If searchPos = 0 Then

                'not found

                _hasMoved = False

                Return -1

            Else

                'found

                Position = searchPos + SearchText.Length

                _hasMoved = True

                Return Position

            End If

        End Function

        Public Function MovePrev(ByVal SearchText As String) As Integer

            Dim searchPos As Integer = InStrRev(Text, SearchText, Position)

            If searchPos = 0 Then

                'not found

                _hasMoved = False

                Return -1

            Else

                'found

                Position = searchPos + SearchText.Length

                _hasMoved = True

                Return Position

            End If

        End Function

        ''' <summary>
        ''' Sposta il puntatore nel file (Position) al carattere successivo alla prima occorrenza della stringa cercata
        ''' </summary>
        ''' <param name="SearchText">La stringa da cercare</param>
        ''' <returns>Restituisce il testo contenuto fra la posizione antecedente del puntatore e l'inizio della stringa cercata, se questa viene trovata; altrimenti restituisce String.Empty.</returns>
        ''' <remarks></remarks>
        Public Function GetTextAndMoveNext(ByVal SearchText As String) As String

            Dim oldPos As Integer = Position
            Dim newPos As Integer = MoveNext(SearchText)

            If newPos = -1 Then

                Return String.Empty

            Else

                Return Mid(Text, oldPos, newPos - oldPos - SearchText.Length)

            End If

        End Function

        ''' <summary>
        ''' Restituisce True se il TextShouldBeBefore si trova posizionato prima di TextShouldBeAfter.
        ''' </summary>
        ''' <param name="TextShouldBeBefore">Testo che dovrebbe stare prima.</param>
        ''' <param name="TextShouldBeAfter">Testo che dovrebbe stare dopo.</param>
        ''' <param name="ThrowExceptionIfTextShouldBeAfterNotFound">Determina se lanciare un'eccezione nel caso TextShouldBeAfter non sia trovata.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function IsTextAfter(ByVal TextShouldBeBefore As String, ByVal TextShouldBeAfter As String, Optional ByVal ThrowExceptionIfTextShouldBeAfterNotFound As Boolean = True) As Boolean

            Dim beforePosition = InStr(Position, Text, TextShouldBeBefore)

            Dim afterPosition = InStr(Position, Text, TextShouldBeAfter)

            If ThrowExceptionIfTextShouldBeAfterNotFound Then
                If afterPosition = 0 Then
                    Throw New ApplicationException("TextShouldBeAfter text not found.")
                End If
            End If

            If beforePosition = 0 Then
                Return False
            Else
                Return afterPosition >= beforePosition
            End If

        End Function

        ''' <summary>
        ''' Reimposta il puntatore all'interno del file 
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Reset()
            Position = 1
        End Sub

    End Class
End Namespace